#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"

#include <stdio.h>
#include <stdlib.h>

#include "platform.h"
#include "makeparam.h"

/**
 ** lua function: i2c.scan()
 */
static int li2c_scan(lua_State *L)
{
	int count = 0;
	int addr = 0x02; /* all i2c chip responds addr 0. so skip it */
	if(lua_gettop(L))
		lua_settop(L,0); /* clean stack */
		
	for(;addr<=254;addr+=2)
		if(!i2c_writebuffer(addr,NULL,0)){
			lua_pushinteger(L,addr);
			count++;
		}
	
	/* if not fount i2c chip,return -1 */
	if(count==0) lua_pushinteger(L,-1);
	return (count==0?1:count); 
}

const char *err_to_str[] ={
	"",
	"bus busy\n",
	"addr not responds\n",
	"error when send data\n",
	"error when read data\n",
};

/** 
 ** lua function: i2c.write(addr,data1, ... ,datan)
 ** addr: i2c chip device address
 ** data[n]: to be sent
 */
static int li2c_write(lua_State *L)
{
	uint8_t *buf;
	int i,addr,count;
	int errcode;
	
	count = lua_gettop(L);
	if(count<2){
		lua_pushstring(L,"Param error! i2c.write(addr,data1, ... ,datan)!\n");
		lua_error(L);
	}
	
	addr = luaL_checkinteger(L,1);
	if( (addr<0) || (addr>=255) ){
		lua_pushstring(L,"Param error! addr from 0 to 255!\n");
		lua_error(L);
	}
	
	if(!addr){
		lua_pushstring(L,"No enough memory!\n");
		lua_error(L);
	}
	
	buf = malloc(sizeof(uint8_t) * count);
	for(i=0;i<count-1;i++) 
		buf[i]=luaL_checkinteger(L,i+2); /* i+2 is the idx of data1 */
	errcode = i2c_writebuffer(addr,buf,count-1);
	free(buf);
	
	if(errcode) {
		lua_pushstring(L,err_to_str[errcode]);
		lua_error(L);
	}
	return 0;
}

/**
 ** lua function: i2c.read(addr,num)
 **/
static int li2c_read(lua_State *L)
{
	int addr,num;
	uint8_t *buf;
	int i,errcode;
	
	if(lua_gettop(L)!=2){
		lua_pushstring(L,"Param error! i2c.read(addr,num)\n");
		lua_error(L);
	}
	
	addr=luaL_checkinteger(L,1);
	num =luaL_checkinteger(L,2);
	if(!lua_checkstack(L,num)) {
		lua_pushstring(L,"No enough memory\n");
		lua_error(L);
	}
	
	buf=malloc(sizeof(uint8_t)*num);
	if(!buf){
		lua_pushstring(L,"No enough memory\n");
		lua_error(L);
	}
	errcode=i2c_readbuffer(addr,buf,num);
	if(errcode) {
		lua_pushstring(L,err_to_str[errcode]);
		lua_error(L);
	}
	else
		for(i=0;i<num;i++) lua_pushinteger(L,buf[i]);
		
	return errcode?0:num;
}

static const luaL_Reg i2cLib[] = {
	{"scan",li2c_scan},
	{"write",li2c_write},
	{"read",li2c_read},
	{NULL,NULL},
};

LUAMOD_API int luaopen_i2c (lua_State *L)
{
	luaL_newlib(L,i2cLib);
	return 1;
}
